﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Platform.LanguageProcessing.Expressions;

namespace Platform.LanguageProcessing
{

	public sealed class GrammarParserStack
	{
		private LinkedList<GrammarExpression> expressions = new LinkedList<GrammarExpression>();


		/// <summary>
		/// 
		/// </summary>
		public int Count
		{ get { return this.expressions.Count; } }

		public bool IsEmpty
		{ get { return this.Count == 0; } }

		public GrammarExpression Top
		{ get { return this.Peek(); } }

		public GrammarExpression Previous
		{
			get
			{
				var node = this.expressions.Last.Previous;
				if ( node != null )
					return node.Value;
				else
					return null;
			}
		}

		//public IEnumerable<GrammarExpression> GetRange( int skipFromTop, int len )
		//{
		//	if ( len < 0 )
		//		throw new ArgumentException();

		//	var cNode = this.Dig( skipFromTop );

		//	while ( len-- > 0 && cNode != null )
		//	{
		//		yield return cNode.Value;
		//		cNode = cNode.Previous;
		//	}
		//}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="top"></param>
		/// <param name="bottom"></param>
		/// <returns></returns>
		public IEnumerable<GrammarExpression> GetTopToBottom( LinkedListNode<GrammarExpression> top, LinkedListNode<GrammarExpression> bottom )
		{
			LinkedListNode<GrammarExpression> cNode = top;

			while ( cNode != null
				&& !cNode.Equals( bottom ) )
			{
				yield return cNode.Value;
				cNode = cNode.Previous;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="skipFromTop"></param>
		/// <param name="len"></param>
		/// <param name="replaceBy"></param>
		public void Replace( LinkedListNode<GrammarExpression> top, LinkedListNode<GrammarExpression> bottom, GrammarExpression replaceBy )
		{
			//if ( len < 0 )
			//	throw new ArgumentException();

			//var cNode = this.Dig( skipFromTop );
			var cNode = top;

			while ( cNode != null
				&& !bottom.Equals( cNode ) )
			{
				var toDelete = cNode;
				cNode = cNode.Previous;

				this.expressions.Remove( toDelete );
			}

			if ( cNode == null )
				this.expressions.AddFirst( replaceBy );
			else
				this.expressions.AddAfter( cNode, replaceBy );
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="expression"></param>
		public void Push( GrammarExpression expression )
		{
			this.expressions.AddLast( expression );
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public GrammarExpression Pop()
		{
			try
			{
				return this.Peek();
			}
			finally
			{
				this.expressions.RemoveLast();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public GrammarExpression Peek()
		{
			return this.Dig( 0 ).Value;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="skip"></param>
		/// <returns></returns>
		public LinkedListNode<GrammarExpression> Dig( int skip )
		{
			if ( skip < 0 || skip >= this.Count )
				throw new IndexOutOfRangeException();

			var node = this.expressions.Last;

			while ( skip-- > 0 )
			{
				node = node.Previous;
			}
			return node;
		}
	}



	///// <summary>
	///// 
	///// </summary>
	//public sealed class GrammarParserStack : IEnumerable<GrammarExpression>
	//{
	//	private List<GrammarExpression> expressions = new List<GrammarExpression>();


	//	public GrammarParserStack()
	//	{ }

	//	/// <summary>
	//	/// 
	//	/// </summary>
	//	public bool IsEmpty
	//	{
	//		get { return this.expressions.Count == 0; }
	//	}

	//	public GrammarExpression Previous
	//	{
	//		get
	//		{
	//			int index = this.TopIndex() - 1;
	//			return ( index < 0 ) ? null : this.expressions[ index ];
	//		}
	//	}

	//	public GrammarExpression Last
	//	{
	//		get
	//		{
	//			return this.expressions[ this.TopIndex() ];
	//		}
	//	}

	//	public IEnumerable<GrammarExpression> GetWindow( StackWindow window )
	//	{
	//		for ( int index = window.Start; index < window.Length; index++ )
	//			yield return this.expressions[ index ];
	//	}

	//	public void ReplaceWindow( StackWindow window, GrammarExpression exp )
	//	{
	//		int len = window.Length;

	//		while ( len-- > 0 )
	//		{
	//			this.expressions.RemoveAt( window.Start );
	//		}
	//		this.expressions.Insert( window.Start, exp );
	//	}

	//	public void Push( GrammarExpression e )
	//	{
	//		this.expressions.Add( e );
	//	}

	//	public GrammarExpression Peek()
	//	{
	//		return this.expressions[ this.TopIndex() ];
	//	}

	//	public GrammarExpression Pop()
	//	{
	//		int index = this.TopIndex();
	//		try
	//		{
	//			return this.expressions[ index ];
	//		}
	//		finally
	//		{
	//			this.expressions.RemoveAt( index );
	//		}
	//	}

	//	private int TopIndex()
	//	{
	//		return this.expressions.Count - 1;
	//	}

	//	public StackEnumerator GetCrawler()
	//	{
	//		return new StackEnumerator( this.expressions );
	//	}

	//	#region IEnumerable<GrammarExpression> Members

	//	public IEnumerator<GrammarExpression> GetEnumerator()
	//	{
	//		return Enumerable.Reverse( this.expressions ).GetEnumerator();
	//	}

	//	#endregion

	//	#region IEnumerable Members

	//	System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
	//	{
	//		return this.GetEnumerator();
	//	}

	//	#endregion

	//	#region [ class StackWindow ]

	//	/// <summary>
	//	/// 
	//	/// </summary>
	//	public class StackWindow
	//	{
	//		public StackWindow( int start, int len )
	//		{
	//			this.Start = start;
	//			this.Length = len;
	//		}

	//		public int Start
	//		{ get; private set; }

	//		public int Length
	//		{ get; private set; }

	//		internal void MoveWindow( int newPosition )
	//		{
	//			this.Length = this.Start - newPosition;
	//			this.Start = newPosition;
	//		}
	//	}

	//	#endregion

	//	#region [ sealed class StackEnumerator ]

	//	public sealed class StackEnumerator : IEnumerator<GrammarExpression>
	//	{
	//		private List<GrammarExpression> list;
	//		private int cursor = -1;

	//		internal StackEnumerator( List<GrammarExpression> list )
	//		{
	//			this.list = list;
	//			this.Reset();
	//		}

	//		public StackWindow OpenWindow()
	//		{
	//			return new StackWindow( this.cursor, -1 );
	//		}

	//		public void Close( StackWindow window )
	//		{
	//			window.MoveWindow( this.cursor );
	//		}

	//		#region IEnumerator<GrammarExpression> Members

	//		public GrammarExpression Current
	//		{
	//			get { return this.list[ this.cursor ]; }
	//		}

	//		#endregion

	//		#region IDisposable Members

	//		public void Dispose()
	//		{ }

	//		#endregion

	//		#region IEnumerator Members

	//		object System.Collections.IEnumerator.Current
	//		{
	//			get { return this.Current; }
	//		}

	//		public bool MoveNext()
	//		{
	//			return --this.cursor >= 0;
	//		}

	//		public void Reset()
	//		{
	//			this.cursor = this.list.Count;
	//		}

	//		#endregion
	//	}

	//	#endregion
	//}
}
